import 'dart:async';
import 'dart:io';
import 'package:get/get.dart';
import 'package:path/path.dart' as path;

import '../models/virtual_file_node.dart';
import '../models/file_metadata.dart';
import '../models/upload_task.dart';
import '../models/download_task.dart';
import 'database_service.dart';
import 'tianyi_cloud_service.dart';
import 'file_manager_service.dart';
import 'upload/upload_service.dart';
import 'download/download_service.dart';
import 'notification_service.dart';
import 'preferences_service.dart';

enum SyncStatus {
  idle,
  syncing,
  completed,
  failed,
  paused,
}

enum SyncDirection {
  upload,
  download,
  bidirectional,
}

class SyncConflict {
  final String localPath;
  final VirtualFileNode localNode;
  final VirtualFileNode cloudNode;
  final DateTime localModified;
  final DateTime cloudModified;
  
  SyncConflict({
    required this.localPath,
    required this.localNode,
    required this.cloudNode,
    required this.localModified,
    required this.cloudModified,
  });
}

class SyncResult {
  final int uploadedFiles;
  final int downloadedFiles;
  final int conflictFiles;
  final int errorFiles;
  final Duration duration;
  final List<String> errors;
  
  SyncResult({
    required this.uploadedFiles,
    required this.downloadedFiles,
    required this.conflictFiles,
    required this.errorFiles,
    required this.duration,
    required this.errors,
  });
}

class SyncService extends GetxService {
  final DatabaseService _databaseService = Get.find<DatabaseService>();
  final TianyiCloudService _cloudService = Get.find<TianyiCloudService>();
  final FileManagerService _fileManagerService = Get.find<FileManagerService>();
  final UploadService _uploadService = Get.find<UploadService>();
  final DownloadService _downloadService = Get.find<DownloadService>();
  final NotificationService _notificationService = Get.find<NotificationService>();
  final PreferencesService _preferencesService = Get.find<PreferencesService>();
  
  // 同步状态
  final Rx<SyncStatus> _syncStatus = SyncStatus.idle.obs;
  SyncStatus get syncStatus => _syncStatus.value;
  
  // 同步进度
  final RxDouble _syncProgress = 0.0.obs;
  double get syncProgress => _syncProgress.value;
  
  // 同步统计
  final RxInt _totalFiles = 0.obs;
  final RxInt _processedFiles = 0.obs;
  final RxString _currentFile = ''.obs;
  
  int get totalFiles => _totalFiles.value;
  int get processedFiles => _processedFiles.value;
  String get currentFile => _currentFile.value;
  
  // 冲突列表
  final RxList<SyncConflict> _conflicts = <SyncConflict>[].obs;
  List<SyncConflict> get conflicts => _conflicts;
  
  // 自动同步定时器
  Timer? _autoSyncTimer;
  
  // 同步取消标志
  bool _isCancelled = false;
  
  @override
  Future<void> onInit() async {
    super.onInit();
    _startAutoSync();
  }
  
  @override
  void onClose() {
    _autoSyncTimer?.cancel();
    super.onClose();
  }
  
  // 启动自动同步
  void _startAutoSync() {
    if (!_preferencesService.getAutoSync()) return;
    
    final interval = _preferencesService.getSyncInterval();
    _autoSyncTimer = Timer.periodic(Duration(minutes: interval), (_) {
      if (_syncStatus.value == SyncStatus.idle) {
        startSync();
      }
    });
  }
  
  // 重启自动同步
  void restartAutoSync() {
    _autoSyncTimer?.cancel();
    _startAutoSync();
  }
  
  // 开始同步
  Future<SyncResult> startSync({
    SyncDirection direction = SyncDirection.bidirectional,
    String? specificPath,
  }) async {
    if (_syncStatus.value == SyncStatus.syncing) {
      throw Exception('同步正在进行中');
    }
    
    _syncStatus.value = SyncStatus.syncing;
    _syncProgress.value = 0.0;
    _totalFiles.value = 0;
    _processedFiles.value = 0;
    _currentFile.value = '';
    _conflicts.clear();
    _isCancelled = false;
    
    final startTime = DateTime.now();
    int uploadedFiles = 0;
    int downloadedFiles = 0;
    int conflictFiles = 0;
    int errorFiles = 0;
    final errors = <String>[];
    
    try {
      // 显示同步开始通知
      if (_preferencesService.getSyncNotification()) {
        await _notificationService.showSyncStartNotification();
      }
      
      // 获取本地和云端文件列表
      final localFiles = await _getLocalFiles(specificPath);
      final cloudFiles = await _getCloudFiles(specificPath);
      
      _totalFiles.value = localFiles.length + cloudFiles.length;
      
      // 分析文件差异
      final syncPlan = await _analyzeSyncPlan(localFiles, cloudFiles, direction);
      
      // 处理上传
      if (direction == SyncDirection.upload || direction == SyncDirection.bidirectional) {
        for (final file in syncPlan.filesToUpload) {
          if (_isCancelled) break;
          
          try {
            _currentFile.value = file.name;
            await _uploadFile(file);
            uploadedFiles++;
          } catch (e) {
            errors.add('上传失败 ${file.name}: $e');
            errorFiles++;
          }
          
          _processedFiles.value++;
          _updateProgress();
        }
      }
      
      // 处理下载
      if (direction == SyncDirection.download || direction == SyncDirection.bidirectional) {
        for (final file in syncPlan.filesToDownload) {
          if (_isCancelled) break;
          
          try {
            _currentFile.value = file.name;
            await _downloadFile(file);
            downloadedFiles++;
          } catch (e) {
            errors.add('下载失败 ${file.name}: $e');
            errorFiles++;
          }
          
          _processedFiles.value++;
          _updateProgress();
        }
      }
      
      // 处理冲突
      conflictFiles = syncPlan.conflicts.length;
      _conflicts.addAll(syncPlan.conflicts);
      
      final duration = DateTime.now().difference(startTime);
      final result = SyncResult(
        uploadedFiles: uploadedFiles,
        downloadedFiles: downloadedFiles,
        conflictFiles: conflictFiles,
        errorFiles: errorFiles,
        duration: duration,
        errors: errors,
      );
      
      _syncStatus.value = _isCancelled ? SyncStatus.paused : SyncStatus.completed;
      
      // 显示同步完成通知
      if (_preferencesService.getSyncNotification()) {
        await _notificationService.showSyncCompleteNotification(
          uploadedFiles,
          downloadedFiles,
          conflictFiles,
        );
      }
      
      return result;
      
    } catch (e) {
      _syncStatus.value = SyncStatus.failed;
      errors.add('同步失败: $e');
      
      // 显示同步失败通知
      if (_preferencesService.getSyncNotification()) {
        await _notificationService.showSyncFailedNotification(e.toString());
      }
      
      final duration = DateTime.now().difference(startTime);
      return SyncResult(
        uploadedFiles: uploadedFiles,
        downloadedFiles: downloadedFiles,
        conflictFiles: conflictFiles,
        errorFiles: errorFiles,
        duration: duration,
        errors: errors,
      );
    }
  }
  
  // 暂停同步
  void pauseSync() {
    _isCancelled = true;
    _syncStatus.value = SyncStatus.paused;
  }
  
  // 恢复同步
  Future<SyncResult> resumeSync() async {
    if (_syncStatus.value != SyncStatus.paused) {
      throw Exception('没有可恢复的同步任务');
    }
    
    return await startSync();
  }
  
  // 获取本地文件列表
  Future<List<VirtualFileNode>> _getLocalFiles(String? specificPath) async {
    if (specificPath != null) {
      return await _databaseService.getFilesByPath(specificPath);
    } else {
      return await _databaseService.getAllFiles();
    }
  }
  
  // 获取云端文件列表
  Future<List<VirtualFileNode>> _getCloudFiles(String? specificPath) async {
    final cloudFiles = <VirtualFileNode>[];
    
    // 递归获取云端文件
    await _getCloudFilesRecursive('/', cloudFiles);
    
    if (specificPath != null) {
      return cloudFiles.where((file) => file.path.startsWith(specificPath)).toList();
    }
    
    return cloudFiles;
  }
  
  // 递归获取云端文件
  Future<void> _getCloudFilesRecursive(String cloudPath, List<VirtualFileNode> result) async {
    try {
      final files = await _cloudService.listFiles(cloudPath);
      
      for (final file in files) {
        result.add(file);
        
        if (file.isFolder) {
          await _getCloudFilesRecursive(file.path, result);
        }
      }
    } catch (e) {
      print('获取云端文件失败: $cloudPath, $e');
    }
  }
  
  // 分析同步计划
  Future<_SyncPlan> _analyzeSyncPlan(
    List<VirtualFileNode> localFiles,
    List<VirtualFileNode> cloudFiles,
    SyncDirection direction,
  ) async {
    final filesToUpload = <VirtualFileNode>[];
    final filesToDownload = <VirtualFileNode>[];
    final conflicts = <SyncConflict>[];
    
    // 创建路径映射
    final localFileMap = <String, VirtualFileNode>{};
    final cloudFileMap = <String, VirtualFileNode>{};
    
    for (final file in localFiles) {
      localFileMap[file.path] = file;
    }
    
    for (final file in cloudFiles) {
      cloudFileMap[file.path] = file;
    }
    
    // 分析本地文件
    for (final localFile in localFiles) {
      if (localFile.isFolder) continue;
      
      final cloudFile = cloudFileMap[localFile.path];
      
      if (cloudFile == null) {
        // 本地文件不存在于云端，需要上传
        if (direction == SyncDirection.upload || direction == SyncDirection.bidirectional) {
          filesToUpload.add(localFile);
        }
      } else {
        // 文件在两端都存在，检查是否有冲突
        final conflict = await _checkFileConflict(localFile, cloudFile);
        if (conflict != null) {
          conflicts.add(conflict);
        }
      }
    }
    
    // 分析云端文件
    for (final cloudFile in cloudFiles) {
      if (cloudFile.isFolder) continue;
      
      final localFile = localFileMap[cloudFile.path];
      
      if (localFile == null) {
        // 云端文件不存在于本地，需要下载
        if (direction == SyncDirection.download || direction == SyncDirection.bidirectional) {
          filesToDownload.add(cloudFile);
        }
      }
    }
    
    return _SyncPlan(
      filesToUpload: filesToUpload,
      filesToDownload: filesToDownload,
      conflicts: conflicts,
    );
  }
  
  // 检查文件冲突
  Future<SyncConflict?> _checkFileConflict(
    VirtualFileNode localFile,
    VirtualFileNode cloudFile,
  ) async {
    // 获取本地文件信息
    final localPath = await _getLocalFilePath(localFile);
    if (localPath == null) return null;
    
    final localFileInfo = File(localPath);
    if (!await localFileInfo.exists()) return null;
    
    final localModified = await localFileInfo.lastModified();
    final cloudModified = cloudFile.updatedTime ?? cloudFile.createdTime;
    
    // 检查修改时间差异（超过1分钟认为有冲突）
    final timeDiff = localModified.difference(cloudModified).abs();
    if (timeDiff.inMinutes > 1) {
      return SyncConflict(
        localPath: localPath,
        localNode: localFile,
        cloudNode: cloudFile,
        localModified: localModified,
        cloudModified: cloudModified,
      );
    }
    
    return null;
  }
  
  // 获取本地文件路径
  Future<String?> _getLocalFilePath(VirtualFileNode node) async {
    // 这里需要根据实际的本地文件存储策略来实现
    // 可能需要从数据库中查询对应的本地路径
    return null;
  }
  
  // 上传文件
  Future<void> _uploadFile(VirtualFileNode file) async {
    final localPath = await _getLocalFilePath(file);
    if (localPath == null) {
      throw Exception('找不到本地文件路径');
    }
    
    final localFile = File(localPath);
    if (!await localFile.exists()) {
      throw Exception('本地文件不存在');
    }
    
    // 添加到上传队列
    await _uploadService.addUploadTask(localFile, file.path);
    
    // 等待上传完成
    await _waitForUploadComplete(localFile.path);
  }
  
  // 下载文件
  Future<void> _downloadFile(VirtualFileNode file) async {
    // 获取文件元数据
    final metadata = await _databaseService.getFileMetadataByCloudId(file.fileMd5!);
    if (metadata == null) {
      throw Exception('找不到文件元数据');
    }
    
    // 添加到下载队列
    await _downloadService.addDownloadTask(file, metadata);
    
    // 等待下载完成
    await _waitForDownloadComplete(file.id);
  }
  
  // 等待上传完成
  Future<void> _waitForUploadComplete(String filePath) async {
    while (true) {
      final tasks = _uploadService.uploadTasks
          .where((task) => task.filePath == filePath)
          .toList();
      
      if (tasks.isEmpty) break;
      
      final task = tasks.first;
      if (task.isCompleted || task.isFailed || task.isCancelled) {
        if (task.isFailed) {
          throw Exception(task.errorMessage ?? '上传失败');
        }
        break;
      }
      
      await Future.delayed(const Duration(milliseconds: 500));
    }
  }
  
  // 等待下载完成
  Future<void> _waitForDownloadComplete(String fileId) async {
    while (true) {
      final tasks = _downloadService.downloadTasks
          .where((task) => task.cloudId == fileId)
          .toList();
      
      if (tasks.isEmpty) break;
      
      final task = tasks.first;
      if (task.isCompleted || task.isFailed || task.isCancelled) {
        if (task.isFailed) {
          throw Exception(task.errorMessage ?? '下载失败');
        }
        break;
      }
      
      await Future.delayed(const Duration(milliseconds: 500));
    }
  }
  
  // 解决冲突
  Future<void> resolveConflict(
    SyncConflict conflict,
    ConflictResolution resolution,
  ) async {
    switch (resolution) {
      case ConflictResolution.useLocal:
        await _uploadFile(conflict.localNode);
        break;
      case ConflictResolution.useCloud:
        final metadata = await _databaseService.getFileMetadataByCloudId(conflict.cloudNode.fileMd5!);
        if (metadata != null) {
          await _downloadFile(conflict.cloudNode);
        }
        break;
      case ConflictResolution.keepBoth:
        // 重命名本地文件并上传
        final newName = _generateConflictName(conflict.localNode.name);
        final renamedNode = conflict.localNode.copyWith(name: newName);
        await _uploadFile(renamedNode);
        break;
      case ConflictResolution.skip:
        // 跳过，不做任何操作
        break;
    }
    
    _conflicts.removeWhere((c) => 
      c.localNode.id == conflict.localNode.id && 
      c.cloudNode.id == conflict.cloudNode.id
    );
  }
  
  // 生成冲突文件名
  String _generateConflictName(String originalName) {
    final timestamp = DateTime.now().millisecondsSinceEpoch;
    final extension = path.extension(originalName);
    final nameWithoutExt = path.basenameWithoutExtension(originalName);
    return '${nameWithoutExt}_conflict_$timestamp$extension';
  }
  
  // 更新进度
  void _updateProgress() {
    if (_totalFiles.value > 0) {
      _syncProgress.value = (_processedFiles.value / _totalFiles.value * 100).clamp(0.0, 100.0);
    }
  }
  
  // 获取同步统计
  Map<String, dynamic> getSyncStatistics() {
    return {
      'status': _syncStatus.value.toString(),
      'progress': _syncProgress.value,
      'totalFiles': _totalFiles.value,
      'processedFiles': _processedFiles.value,
      'currentFile': _currentFile.value,
      'conflicts': _conflicts.length,
    };
  }
}

class _SyncPlan {
  final List<VirtualFileNode> filesToUpload;
  final List<VirtualFileNode> filesToDownload;
  final List<SyncConflict> conflicts;
  
  _SyncPlan({
    required this.filesToUpload,
    required this.filesToDownload,
    required this.conflicts,
  });
}

enum ConflictResolution {
  useLocal,
  useCloud,
  keepBoth,
  skip,
}